Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Peer Discovery DEP #7

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

pfrazee
Copy link
Contributor

@pfrazee pfrazee commented Feb 7, 2018

This one is almost ready to go. Needs review and a few TODO items which should be easy to resolve.

TODOs

  • add a section about hole punching
  • add a section about the discovery key
  • fix possible amplification attack?
  • Some things Maf and I plan to change in the implementation in a debug session soon:
    • fix encoding to include all 32 bytes (not the 20 currently)
    • switch to blake2b in token gen
    • rethink how push works to make sure we notify (almost) everyone, or possibly switch to pull only
    • consider a new hole-punching system that replaces push announcements

@pfrazee pfrazee changed the title Add proposals/0000-peer-discovery.md (WIP) Peer Discovery DEP (WIP) Feb 7, 2018

Multicast DNS (mDNS) resolves host names to IP addresses within small networks without a local name server. It is a zero-configuration service, using essentially the same interfaces, packet formats and operating semantics as unicast DNS. The mDNS protocol is published as [RFC 6762](https://tools.ietf.org/html/rfc6762) and is built on multicast UDP.

Dat treats Hypercore public keys as domain names on the mDNS protocol. Therefore, peer discovery is an IP lookup for a given public key name. Currently the public key is encoded to hex and truncated to 40 bytes. The domain name format used is:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not the public key, but the hypercore discovery key. This is an important detail. We never expose the public key over the network, as it is used as a capability

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's truncated because dns subdomains can at most be 63 chars also

Peer listings are a base64-encoded buffer of 6-byte peer items. Each peer item is packed as follows:

```
{4 bytes: IPv4 address}{2 bytes: port}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's big endian port

To verify the addresses of clients, the DNS discovery protocol uses a session token exchange. All clients must first request a token before sending protocol messages. The server will generate the token using the following algorithm:

```
sha256(secret + client-address)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personal note that we should use blake2b here instead


The token is requested by sending a `TXT` record to the DNS server with a target name of `"dat.local"`. The server will respond with the token, plus the port and address of the sending device (which are useful as a "whoami").

Over time, the server will rotate the secret it uses to generate tokens. In order to update clients' tokens, every response includes the latest token. The client should update its token with every response it receives. (It's advised that the server keeps the most recently expired secre so that old tokens can be accepted and replaced smoothly.)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

secre -> secret

{PUBKEY}.dat.local
```

Dat uses the `TXT` record type. A query is submitted as a simple `TXT` query for `{PUBKEY}.dat.local`. The response provides a peer-listing which will only include the local node, if it is actively hosting the requested Hypercore.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{DISCOVERY_KEY}.dat.local

### Lookup query
[dns-name-server-lookup-query]: #dns-name-server-lookup-query

To request the current list of known peers for a pubkey, send a `TXT` question query with `{PUBKEY}.dat.local` as the name. Currently the public key is encoded to hex and truncated to 40 bytes. You will receive a response that includes a full peer listing and the latest token. See "TXT data encoding" above for information about encoding.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{DISCOVERY_KEY}.dat.local


If a `TXT` lookup query is sent with an "additional" section that does not have the `subscribe` flag, that is treated as an "unsubscribe" message and the device is removed from the active listeners.

TODO- what's the TTL?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, I think its 1-2min


The `announce` field instructs the DNS name server to add the device to the list of active hosting peers for the given Hypercore. Its value should be the port from which the device is listening. Multiple ports may be announced using separate queries. Upon announce, the new peer is pushed to any subscribed devices using an `SRV` query.

TODO- how long till announce records expire? Should the client reannounce periodically?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes they should. They are GC'ed every 5-10 mins


Mainline DHT is the name given to the Kademlia-based Distributed Hash Table (DHT) used by BitTorrent clients to find peers. Dat has adopted it temporarily to track peers in its own network. You can find the specification at [BEP 0005](http://www.bittorrent.org/beps/bep_0005.html).

There are some issues with Dat's use of Mainline which limit the usefulness of its function. BitTorrent uses a 20 byte sha1 hash to identify torrents, while Dat uses a 32 byte public key to identify Hypercore registers. As a result, Dat has to truncate its keys to the first 20 bytes, leading to false positives when connecting to peers.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

discovery key

# Privacy concerns
[privacy-concerns]: #privacy-concerns

Peer discovery networks reveal the participants in a Dat swarm to any device which can access the network. This presents a privacy risk for users who may not want to have their activity broadcasted.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main thing leaked is who is talking to who (which is of course important). we never leak the capability (public key) so passive listeners cannot access data / decrypt data - they can also see Alice and Bob are talking to each other probably

Copy link

@anarcat anarcat Aug 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's important to indicate who that information is leaked to. elsewhere in the documentation (e.g. in the security FAQ) we are lead to believe that information is leaked only to the members of the swarm, which is not really accurate. sure, the contents are visible only to the members of the swarm, but metadata like public (and private?) IP addresses and relationships between people are spread out much more widely that I first believed when reviewing the protocol.

in particular, if i understand this DEP correctly, it implies that discoverN.datproject.org know precisely:

  1. when a peer comes online (when Alice runs dat share)
  2. when a peer looks for content (when Bob runs dat clone $ALICEHASH)
  3. that Alice and Bob are related

This raises all sorts of privacy concerns which should be answered by the dat project. For example:

  • does the discovery server keep logs?
  • what is the retention policy?
  • who has access to those logs?

I think the current section about Privacy concerns is great, but should be expanded to cover for this peculiar property of the protocol. The security FAQ should also be updated to mention this, but that's a separate issue: I've documented my concerns with that in dat-ecosystem-archive/docs#127

# Unresolved questions
[unresolved]: #unresolved-questions

- Does the DNS network *need* to truncate the public key to 40 bytes? Could we fit the full 64 bytes by using another level of subdomain?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea good idea. 32-chars.32-chars or use an encoding other than hex that is still dns friendly. Thoughts?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could hash the discovery key to something like 63 bytes?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smart

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we hash to 63 bytes (not change encoding) we're basically just losing a byte of specificity. Why not just do 32.32 and stick with hex? We could also switch to base32.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

32.32 seems reasonable.

Copy link
Contributor

@bnewbold bnewbold left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good start! I think the main thing is pubkey/discovery key confusion.

I might have more detailed comments after I implement more of these mechanisms; right now geniza just does passive lookups.

EDIT: whoops, looks like these comments might be redundant with maf's; I made these asynchronously and just got back to an internet connection now.


An important aspect of Dat's networking is peer discovery, the techniques that peers use to find each other. Peer discovery means finding the IP and port of data sources online that have a copy of that data you are looking for. You can then connect to them and begin exchanging data. By using peer discovery techniques Dat is able to create a network where data can be discovered even if the original data source disappears.

Peer discovery can happen over many kinds of networks, as long as you can model the following actions:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how I feel about encoding these function signatures here. I did something similar in the hyperdb DEP, but here it feels really specific to the existing dat implementation. Maybe just describe what semantics are necessary for lookup, and what additional semantics are necessary to announce/cancel membership or subscribe to a feed of peer updates?


Multicast DNS (mDNS) resolves host names to IP addresses within small networks without a local name server. It is a zero-configuration service, using essentially the same interfaces, packet formats and operating semantics as unicast DNS. The mDNS protocol is published as [RFC 6762](https://tools.ietf.org/html/rfc6762) and is built on multicast UDP.

Dat treats Hypercore public keys as domain names on the mDNS protocol. Therefore, peer discovery is an IP lookup for a given public key name. Currently the public key is encoded to hex and truncated to 40 bytes. The domain name format used is:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure we use discovery keys (not public keys) for all discovery mechanisms.

The discovery key is a BLAKE2b "keyed hash" of the string "hypercore" using the public key (32 bytes), described in the wire protocol DEP (WIP).

Over time, the server will rotate the secret it uses to generate tokens. In order to update clients' tokens, every response includes the latest token. The client should update its token with every response it receives. (It's advised that the server keeps the most recently expired secre so that old tokens can be accepted and replaced smoothly.)


### Lookup query
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SRV requests are also possible. Eg, on the command line:

dig @discovery1.publicbits.org 905fd1b6504698425e8bec3dbb77d757e281d505.dat.local SRV

returns something like:

0 0 44113 172.19.0.4.

Which, IIRC, is port 44113 on host 172.19.0.4 (note the trailing period, which is not a typo).


The `announce` field instructs the DNS name server to add the device to the list of active hosting peers for the given Hypercore. Its value should be the port from which the device is listening. Multiple ports may be announced using separate queries. Upon announce, the new peer is pushed to any subscribed devices using an `SRV` query.

TODO- how long till announce records expire? Should the client reannounce periodically?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 10 minutes, and clients should re-announce, but I don't have a reference.

There are some issues with Dat's use of Mainline which limit the usefulness of its function. BitTorrent uses a 20 byte sha1 hash to identify torrents, while Dat uses a 32 byte public key to identify Hypercore registers. As a result, Dat has to truncate its keys to the first 20 bytes, leading to false positives when connecting to peers.


# Privacy concerns
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are two other privacy concerns off the top of my head:

  • the concern of being able to discovery (and potentially download) all content "discovered" via these mechanisms. This is mitigated by using discovery keys (instead of public keys) for download
  • the ability to discover who has what content on the network (if you know a priori what content is associated with which discovery keys). Eg, imagine somebody sharing leaked documents; if the documents (dat archive, and thus discovery key) become public, somebody can make a list of all peers who have exchanged (or "knew of") that archive. I don't know any mitigation for this right now. This is also a concern with the wire protocol; in that case it could be mitigated by encrypting the entire transaction (including the discovery key verification), but not with the current encryption scheme.

### Lookup query
[dns-name-server-lookup-query]: #dns-name-server-lookup-query

To request the current list of known peers for a pubkey, send a `TXT` question query with `{PUBKEY}.dat.local` as the name. Currently the public key is encoded to hex and truncated to 40 bytes. You will receive a response that includes a full peer listing and the latest token. See "TXT data encoding" above for information about encoding.
Copy link

@tristanls tristanls Feb 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will receive a response that includes a full peer listing

If I go through a valid "probe" step, acquire a session token, and then announce multiple ports, that would seem to increase the full peer listing arbitrarily.

Since simple lookups do not require a token, then it should be possible for me to spoof the IP address in simple lookups and use (previously constructed) arbitrarily large full peer listing to execute DoS on a target.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good find, this is a weakness cc @mafintosh

@pfrazee
Copy link
Contributor Author

pfrazee commented Feb 15, 2018

Ok I covered most feedback (thanks all!). A few TODOs are written in the Unresolved questions. There's also some changes that we're going to implement in March, so I'm going to leave this DEP for now.

@pfrazee pfrazee changed the title Peer Discovery DEP (WIP) WIP: Peer Discovery DEP Mar 4, 2018
Copy link

@anarcat anarcat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The privacy concerns section should be expanded to cover discoveryN.datproject.org more explicitely, details in comment above.

# Privacy concerns
[privacy-concerns]: #privacy-concerns

Peer discovery networks reveal the participants in a Dat swarm to any device which can access the network. This presents a privacy risk for users who may not want to have their activity broadcasted.
Copy link

@anarcat anarcat Aug 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's important to indicate who that information is leaked to. elsewhere in the documentation (e.g. in the security FAQ) we are lead to believe that information is leaked only to the members of the swarm, which is not really accurate. sure, the contents are visible only to the members of the swarm, but metadata like public (and private?) IP addresses and relationships between people are spread out much more widely that I first believed when reviewing the protocol.

in particular, if i understand this DEP correctly, it implies that discoverN.datproject.org know precisely:

  1. when a peer comes online (when Alice runs dat share)
  2. when a peer looks for content (when Bob runs dat clone $ALICEHASH)
  3. that Alice and Bob are related

This raises all sorts of privacy concerns which should be answered by the dat project. For example:

  • does the discovery server keep logs?
  • what is the retention policy?
  • who has access to those logs?

I think the current section about Privacy concerns is great, but should be expanded to cover for this peculiar property of the protocol. The security FAQ should also be updated to mention this, but that's a separate issue: I've documented my concerns with that in dat-ecosystem-archive/docs#127

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants